#include "stdafx.h"
#include "UITemplate.h"
#include "JSParse.h"
#include "PythonObject.h"
#include "BridgeComponentBase.h"

void UITemplate::SetScriptInfo(QString scriptFileName, QString mainclass, QString mainFunc, QString strRoadName)
{
	m_scriptFileName = scriptFileName;
	m_mainClassName = mainclass;
	m_mainFunctionName = mainFunc;
	SetRoadName(strRoadName);
	if (!m_scriptFileName.isEmpty())
	{
		SetMeshObject(SharedPointer<MeshObjectBase>());
		ZMVector<SharedPointer<UIDataBase>> vNewParam, vScriptParam;
		ZMVector<SharedPointer<UIDataBase>> vParam = GetParam();
		for (const SharedPointer<UIDataBase>& pParam: vParam)
		{
			if (!pParam->GetAttachFuncName().isEmpty())
			{
				vNewParam.push_back(pParam);
			}
			else
			{
				vScriptParam.push_back(pParam);
			}
		}
		SetParam(vNewParam);

		ZMString strFielName = ToString(m_scriptFileName);
		ZMString strExtName = strFielName.substr(strFielName.find_last_of(".") + 1);

		SharedPointer<MeshObjectBase> pMeshObj;
		if (strExtName == "js")
		{
			pMeshObj = SharedPointer<MeshObjectBase>(new JSParse(ToString(m_scriptFileName)));
		}
		else if (strExtName == "py")
		{
#ifdef USE_SCRIPT_PYTHON
			pMeshObj = SharedPointer<MeshObjectBase>(new PythonObject(ToString(GetTemplateID()), ToString(m_scriptFileName), ToString(mainclass), ToString(mainFunc)));
#else
			assert(false);
#endif
		}
		else if (strExtName == "internal")
		{
			CNameCreateBase* pNameCreate = CObjectCreateFromName::GetInstance()->CreatObjFromName(mainclass);
			BridgeComponentBase *pBridge = dynamic_cast<BridgeComponentBase *>(pNameCreate);
			assert(pBridge);
			pMeshObj = SharedPointer<MeshObjectBase>(pBridge);
		}
		if (pMeshObj.get())
		{
			pMeshObj->SetParam(vScriptParam);;
		}
		SetMeshObject(pMeshObj);
	}
}

void UITemplate::SetMeshObject(SharedPointer<MeshObjectBase> pMeshObject)
{
	if (m_pMeshObject.get())
	{
		m_vUIClass.erase(m_vUIClass.begin() + m_iMeshParamFrom, m_vUIClass.begin() + m_iMeshParamFrom + m_pMeshObject->GetParam().size());
	}
	m_pMeshObject = pMeshObject;
	m_iMeshParamFrom = m_vUIClass.size();
	if (m_pMeshObject.get())
	{
		ZMVector<SharedPointer<UIDataBase>> vParam = m_pMeshObject->GetParam();
		m_vUIClass.insert(m_vUIClass.end(), vParam.begin(), vParam.end());
	}
}

bool UITemplate::IsMeshObjValid() const
{
	bool ret = m_pMeshObject.get();
	if (ret)
	{
		ret = m_pMeshObject->IsVaid();
	}
	return ret;
}

void UITemplate::WriteBinaryData(CStreamSaveData& fp) const
{
	ZMVector<SharedPointer<UIDataBase>> vParam = GetParam();

	for (SharedPointer<UIDataBase> pData : vParam)
	{
		if (pData->GetVarDesti() == UIDataBase::TO_UNIT3d && !pData->GetAttachFuncName().isEmpty())
		{
			pData->WriteBinaryData(fp);
		}
	}

	if (IsMeshObjValid())
	{
		(const_cast<MeshObjectBase*>(m_pMeshObject.get()))->SetParam(GetMeshParam());
	}
}

ZMVector<SharedPointer<UIDataBase>> UITemplate::GetScriptParam() const
{
	ZMVector<SharedPointer<UIDataBase>> ret;
	if (m_pMeshObject.get())
	{
		ZMVector<SharedPointer<UIDataBase>> vParam = GetParam();
		ret.insert(ret.end(), vParam.begin(), vParam.begin() + m_iMeshParamFrom);
		ret.insert(ret.end(), vParam.begin() + m_iMeshParamFrom + m_pMeshObject->GetParam().size(), vParam.end());
	}
	return ret;
}

ZMVector<SharedPointer<UIDataBase>> UITemplate::GetMeshParam() const
{
	ZMVector<SharedPointer<UIDataBase>> ret;
	if (m_pMeshObject.get())
	{
		ZMVector<SharedPointer<UIDataBase>> vParam = GetParam();
		ret.insert(ret.end(), vParam.begin() + m_iMeshParamFrom, vParam.begin() + m_iMeshParamFrom + m_pMeshObject->GetParam().size());
	}
	return ret;
}

ZMVector<SharedPointer<UIDataBase>> UITemplate::GetParam() const
{
	ZMVector<SharedPointer<UIDataBase>> ret = m_vUIClass;
	return m_vUIClass;
}

void UITemplate::AddParam(SharedPointer<UIDataBase> pParam)
{
	m_vUIClass.push_back(pParam);
}

void UITemplate::SetParam(const ZMVector<SharedPointer<UIDataBase>>& vParam)
{
	m_vUIClass = vParam;
	if (m_pMeshObject.get())
	{
		ZMVector<SharedPointer<UIDataBase>> vTemp = m_pMeshObject->GetParam();
		m_iMeshParamFrom = m_vUIClass.size();
		m_vUIClass.insert(m_vUIClass.end(), vTemp.begin(), vTemp.end());
	}
}

void UITemplate::Clear()
{
	m_vUIClass.clear();
	if (m_pMeshObject.get())
	{
		m_vUIClass = m_pMeshObject->GetParam();
		m_iMeshParamFrom = 0;
	}
}

void UITemplate::CreateUI(QStandardItemModel* pModel, ViewItemDelegate*pDelegate, QModelIndex inxParent)
{
	ZMVector<SharedPointer<UIDataBase>> vParam = GetParam();

	for (SharedPointer<UIDataBase> pParam : vParam)
	{
		pParam->CreateUI(pModel, pDelegate, inxParent);
	}
}

void UITemplate::UpdateUI(QTreeView* pView, bool isToScreen, bool &isValueChange)
{
	isValueChange = false;
	ZMVector<SharedPointer<UIDataBase>> vParam = GetParam();
	for (SharedPointer<UIDataBase> pParam : vParam)
	{
		bool bTemp;
		pParam->UpdateUI(pView, isToScreen, bTemp);
		if (bTemp && !isValueChange) isValueChange = !isValueChange;
	}
}

QString UITemplate::GetTemplateID() const { return m_templateID; }

void UITemplate::SetTemplateID(QString val) { m_templateID = val; }

QString UITemplate::GetScriptFileName() const
{
	return m_scriptFileName;
}


ZMString UITemplate::UpdateShowMesh(OgreWidget * pWidget, const ZMString& meshName, const ZMString& parentNodeName, ZMVector<SharedPointer<UIDataBase>> vParamTranform)
{
	ZMString ret;
	if (m_pMeshObject.get())
	{
		ret = meshName == "" ? m_pMeshObject->GetObjName() : meshName;
		m_pMeshObject->SetParam(GetMeshParam());
		m_pMeshObject->UpdateMeshData(pWidget, meshName, parentNodeName);
		
		for (const SharedPointer<UIDataBase>& pParam : vParamTranform)
		{
			ZMVector<SharedPointer<CNameCreateBase>> vCreateParam;
			SharedPointer<CNameCreateBase> pData = SharedPointer<CNameCreateBase>(CObjectCreateFromName::GetInstance()->CreatObjFromName("string", "Param_"));
			((CTemplateParam<string>*)pData.get())->SetData(ret);
			vCreateParam.push_back(pData);

			pData = SharedPointer<CNameCreateBase>(CObjectCreateFromName::GetInstance()->CreatObjFromName(pParam->GetType(), "Param_"));

			CStreamSaveData fp;
			pParam->WriteRealCoreData(fp);
			ZMVector<unsigned char>  vData = fp.GetBinaryData();
			CStreamLoadData fpRead(vData.data(), vData.size());

			((CTemplateParam<InteractionData>*)pData.get())->Read(fpRead);
			vCreateParam.push_back(pData);

			RunFunction func = CObjectCreateFromName::GetInstance()->CreatFuncFromName(pParam->GetAttachFuncName());
			func(vCreateParam);

		}
		ZMVector<SharedPointer<UIDataBase>>  vParam = GetScriptParam();
		for (const SharedPointer<UIDataBase>& pParam : vParam)
		{
			ZMVector<SharedPointer<CNameCreateBase>> vCreateParam;
			SharedPointer<CNameCreateBase> pData = SharedPointer<CNameCreateBase>(CObjectCreateFromName::GetInstance()->CreatObjFromName("string", "Param_"));
			((CTemplateParam<string>*)pData.get())->SetData(ret);
			vCreateParam.push_back(pData);

			pData = SharedPointer<CNameCreateBase>(CObjectCreateFromName::GetInstance()->CreatObjFromName(pParam->GetType(), "Param_"));
			
			CStreamSaveData fp;
			pParam->WriteRealCoreData(fp);
			ZMVector<unsigned char>  vData = fp.GetBinaryData();
			CStreamLoadData fpRead(vData.data(), vData.size());

			((CTemplateParam<InteractionData>*)pData.get())->Read(fpRead);
			vCreateParam.push_back(pData);

			RunFunction func = CObjectCreateFromName::GetInstance()->CreatFuncFromName(pParam->GetAttachFuncName());
			func(vCreateParam);

		}
	}
	return ret;
}

UITemplate UITemplate::CopyTo() const
{
	UITemplate ret = *this;
	ZMVector<SharedPointer<UIDataBase>> vUIClass(m_vUIClass.size());
	for (int i = 0; i < m_vUIClass.size(); ++i)
	{
		vUIClass[i] = m_vUIClass[i]->CopyTo();
	}
	
	ret.SetParam(vUIClass);
	ret.SetScriptInfo(m_scriptFileName, m_mainClassName, m_mainFunctionName, m_strRoadName);
	return ret;
}
